//
//  Manager.swift
//  LZCache
//
//  Created by 湛亚磊 on 2020/3/14.
//  Copyright © 2020 湛亚磊. All rights reserved.
//

import UIKit
import RxSwift
import Moya
import Reachability


///响应的model
public enum LZResponseType:Int {
    case nomal=1
    case netNoData=2
}

extension MoyaProviderType{
    public func getResponse(target: Target,with type:LZResponseType = .nomal,withDebug isDebug:Bool=true) -> Observable<(AnyObject?,Int)> {
        
        let reachability = try! Reachability()
        switch reachability.connection {
            case .cellular,.wifi:
                return Observable.create { [weak self] observer in
                    if isDebug{
                        print("请求的内容g~~~\(target.parameters) ---- >>> \(target.url)")
                    }
                     let cancellableToken = self?.request(target, callbackQueue: .main, progress: nil, completion: { (result) in
                         switch result{
                         case .success(let response):
                             if let baseApi = target as? LZBaseApi{
                                
                                observer.onNext((self?.transform(target: baseApi, with: response, with: type, withDebug: isDebug))!)
                             }
                         case .failure(let error):
                            if isDebug{
                                print("我的错误请求信息\(error)")
                            }
                             /// 判断是否需要缓存
                             if let baseApi = target as? LZBaseApi{
                                 if baseApi.cacheType == .cache{
                                  self?.getCacheAction(baseApi, observer: observer)
                                 }else{
                                     observer.onNext((nil,300001))
                                 }
                             }
                            if isDebug{
                                print("请求失败")
                            }
                             
                         }
                     })
                    
                    return Disposables.create {
                        cancellableToken?.cancel()
                    }
                }
            case .unavailable:
                return Observable<(AnyObject?,Int)>.create { (info) -> Disposable in
                    info.onNext((nil,300002))
                    info.onCompleted()
                    return Disposables.create {}
                }
            default:
                return Observable<(AnyObject?,Int)>.create { (info) -> Disposable in
                    info.onNext((nil,300001))
                    info.onCompleted()
                    return Disposables.create {}
                }
        }

    }
    
    
    private func transform(target: LZBaseApi,with response:Response,with responseType:LZResponseType,withDebug isDebug:Bool) -> (AnyObject?,Int) {
        
        if response.statusCode == 200{
            do {
                
                let dic = try? JSONSerialization.jsonObject(with: response.data, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: Any]
                if isDebug{
                    print("请求的状态====\(dic ?? ["":""])")
                }
                if (dic?["code"] as? Int ?? 500) == 200 {
                    
                    switch responseType {
                    case .nomal:
                        if JSONSerialization.isValidJSONObject(dic?["data"] as Any){
                            let data = try JSONSerialization.data(withJSONObject: dic?["data"] as Any, options: [])
                            if target.cacheType == .cache{
                                setCacheAction(target, data: data, withDebug: isDebug)
                            }
                            
                        }
                        return (dic?["data"] as AnyObject,200)
                    case .netNoData:
                        if target.cacheType == .cache{
                            setCacheAction(target, data: dic?["msg"] as? Data ?? Data(), withDebug: isDebug)
                        }
                        return (dic?["msg"] as AnyObject?,200)
                    }
                }else {
                    return (nil,(dic?["code"] as? Int ?? 500))
                }
            } catch {
                return (nil,200)
            }
        }else { ///服务器异常
            return (nil,response.statusCode)
        }
    }
    
    
    
    
    /// 获取网络缓存
    ///
    /// - Parameters:
    ///   - token: api token
    ///   - observer: rx service
    fileprivate func getCacheAction(_ token: LZBaseApi, observer: AnyObserver<(AnyObject?,Int)>) {
        guard token.cacheType != .none else { return }
        // 先读取缓存内容，有则发出一个信号（onNext），没有则跳过
        LZNSCacheTool.shared.netWork?.async.object(forKey: token.cacheKey, completion: { (result) in
            switch result {
            case .value(let value):
                
                let dic = try? JSONSerialization.jsonObject(with: value, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: Any]
                observer.onNext((dic as AnyObject?,200))
                observer.onCompleted()
            case .error(let error):
                observer.onNext((nil,200))
                observer.onCompleted()
                print("读取缓存失败 \(error.localizedDescription)")
            }
        })
    }

    /// 存入网络缓存
    ///
    /// - Parameters:
    ///   - token: api token
    ///   - data: 存储数据data
    fileprivate func setCacheAction(_ token: LZBaseApi, data: Data,withDebug isDebug:Bool){
        guard token.cacheType != .none else { return }
        if isDebug{
            print("保存的数据~~~~\(data)")
        }
        LZNSCacheTool.shared.netWork?.async.setObject(data, forKey: token.cacheKey, completion: { (result) in
            switch result {
            case .value( _):
                if isDebug{
                    print("缓存成功")
                }
            default:
                if isDebug{
                    print("缓存失败")
                }
            }
        })
    }
}
